home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / stdlib / Mem_PrintStats.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-22  |  7.0 KB  |  268 lines

  1. /* 
  2.  * Mem_PrintStats.c --
  3.  *
  4.  *    Source code for the "Mem_PrintStats" library procedure.  See memInt.h
  5.  *    for overall information about how the allocator works..
  6.  *
  7.  * Copyright 1988 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/lib/c/stdlib/RCS/Mem_PrintStats.c,v 1.5 89/02/10 09:54:31 brent Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21. #include "memInt.h"
  22.  
  23. /*
  24.  * Data structure used to record statistics for the blocks managed by
  25.  * the large block allocator.  Each entry holds information for all the
  26.  * blocks of a given size.
  27.  */
  28.  
  29. #define    MAX_TO_PRINT    256
  30. static struct {
  31.     int        size;        /* Size of the block. */
  32.     int        num;        /* Number of blocks allocated. */
  33.     int        free;        /* Number of blocks freed. */
  34.     int        inUse;        /* Number of blocks still in use. */
  35.     int        dummy;        /* Number of blocks used as dummy blocks. */
  36. } topN[MAX_TO_PRINT + 1];
  37.  
  38. /*
  39.  * Global variables that can be set to control thresholds for printing
  40.  * statistics.
  41.  */
  42.  
  43. int    mem_SmallMinNum = 1;        /* There must be at least this many
  44.                      * binned objects of a size before info
  45.                      * about its size gets printed. */
  46. int    mem_LargeMinNum  = 1;        /* There must be at least this many
  47.                      * non-binned objects of a size before
  48.                      * info about the size gets printed. */
  49. int    mem_LargeMaxSize = 10000;    /* Info is printed for non-binned
  50.                      * objects larger than this regardless
  51.                      * of how many of them there are. */
  52.  
  53. /*
  54.  * Forward declarations to procedures defined in this file:
  55.  */
  56.  
  57. extern void    PrintStatsSubr();
  58.  
  59. /*
  60.  *----------------------------------------------------------------------
  61.  *
  62.  * Mem_PrintStats --
  63.  *
  64.  *    Print out memory statistics, using the default printing routine
  65.  *    and default sizes.
  66.  *
  67.  *    See Mem_PrintStatsInt for details.
  68.  *
  69.  * Results:
  70.  *    None.
  71.  *
  72.  * Side effects:
  73.  *    None.
  74.  *
  75.  *----------------------------------------------------------------------
  76.  */
  77. ENTRY void
  78. Mem_PrintStats()
  79. {
  80.     LOCK_MONITOR;
  81.  
  82.     Mem_PrintStatsInt();
  83.  
  84.     UNLOCK_MONITOR;
  85. }
  86.  
  87. /*
  88.  *----------------------------------------------------------------------
  89.  *
  90.  * Mem_PrintStatsInt --
  91.  *
  92.  *    Print out memory statistics.  Normally called only by
  93.  *    Mem_PrintStats.  It's exported for use after a crash or when
  94.  *    memory has been exhausted.  At this time the monitor lock is
  95.  *    already down, so it better not be reacquired.
  96.  *
  97.  * Results:
  98.  *    None.
  99.  *
  100.  * Side effects:
  101.  *    Information gets printed, using the current print procedure
  102.  *    and the parameter values stored in mem_SmallMinNum,
  103.  *    mem_LargeMinNum, and mem_LargeMaxSize.
  104.  *
  105.  *----------------------------------------------------------------------
  106.  */
  107.  
  108. INTERNAL void
  109. Mem_PrintStatsInt()
  110. {
  111.     register Address    ptr;
  112.     register int    i;
  113.     int        totalBlocks, totalFree;
  114. #ifdef MEM_TRACE
  115.     int totalAllocs;
  116. #endif
  117.     int        allocBytes = 0;
  118.     int        freeBytes = 0;
  119.     int        warnedAboutOverflow;
  120.  
  121.     if (!memInitialized) {
  122.     (*memPrintProc)(memPrintData, "Allocator not initialized yet.\n");
  123.     return;
  124.     }
  125.  
  126. #ifdef MEM_TRACE
  127.     (*memPrintProc)(memPrintData, "\nTotal allocs = %d, frees = %d\n\n",
  128.         mem_NumAllocs, mem_NumFrees);
  129.     totalAllocs = 0;
  130. #else
  131.     (*memPrintProc)(memPrintData, "Memory tracing not enabled, so %s",
  132.         "some statistics won't be printed.\n");
  133. #endif
  134.  
  135.     (*memPrintProc)(memPrintData, "Small object allocator:\n");
  136.     (*memPrintProc)(memPrintData,
  137.         "    Size     Total    Allocs    In Use\n");
  138.     totalBlocks = totalFree = 0;
  139.     for (i = 2; i < BIN_BUCKETS; i++) {
  140.     int    numFree = 0;
  141.  
  142.     if ((memFreeLists[i] == NOBIN) || (mem_NumBlocks[i] == 0)) {
  143.         continue;
  144.     }
  145.     allocBytes += mem_NumBlocks[i] * INDEX_TO_BLOCKSIZE(i);
  146.     for (ptr = memFreeLists[i]; 
  147.          ptr != (Address) NULL; 
  148.          ptr = (Address) GET_ADMIN(ptr)) {
  149.  
  150.         freeBytes += INDEX_TO_BLOCKSIZE(i);
  151.         numFree += 1;
  152.     }
  153.     if (mem_NumBlocks[i] >= mem_SmallMinNum) {
  154. #ifdef MEM_TRACE
  155.         (*memPrintProc)(memPrintData, "%8d%10d%10d%10d\n",
  156.             INDEX_TO_BLOCKSIZE(i),
  157.             mem_NumBlocks[i], mem_NumBinnedAllocs[i],
  158.             mem_NumBlocks[i] - numFree);
  159. #else
  160.         (*memPrintProc)(memPrintData, "%8d%10d%10s%10d\n", 
  161.             INDEX_TO_BLOCKSIZE(i),
  162.             mem_NumBlocks[i], "??", mem_NumBlocks[i] - numFree);
  163. #endif MEM_TRACE
  164.     }
  165.     totalBlocks += mem_NumBlocks[i];
  166. #ifdef MEM_TRACE
  167.     totalAllocs += mem_NumBinnedAllocs[i];
  168. #endif
  169.     totalFree += numFree;
  170.     }
  171. #ifdef MEM_TRACE
  172.     (*memPrintProc)(memPrintData, "   Total%10d%10d%10d\n", totalBlocks,
  173.         totalAllocs, totalBlocks - totalFree);
  174. #else
  175.     (*memPrintProc)(memPrintData, "   Total%10d%10s%10d\n", totalBlocks,
  176.         "??", totalBlocks - totalFree);
  177. #endif
  178.     (*memPrintProc)(memPrintData, "Bytes allocated = %d, free = %d\n\n",
  179.                 allocBytes, freeBytes);
  180.  
  181.     /*
  182.      * Initialize the largest N-sizes buffer.
  183.      */
  184.     for (i = 0; i < MAX_TO_PRINT + 1; i++) {
  185.     topN[i].size = -1;
  186.     topN[i].free = 0;
  187.     topN[i].dummy = 0;
  188.     }
  189.  
  190.     warnedAboutOverflow = 0;
  191.     freeBytes = 0;
  192.     for (ptr = memFirst + SIZE(GET_ADMIN(memFirst)); 
  193.      ptr != memLast;
  194.      ptr += SIZE(GET_ADMIN(ptr))) {
  195.  
  196.     int    admin;
  197.     int    size;
  198.     int    found;
  199.  
  200.     admin = GET_ADMIN(ptr);
  201.     if (!IS_DUMMY(admin) && !IS_IN_USE(admin)) {
  202.         freeBytes += SIZE(admin);
  203.     }
  204.  
  205.     size = SIZE(admin);
  206. #ifdef MEM_TRACE
  207.     if ((size - GET_ORIG_SIZE(ptr) < 4) && 
  208.         (size - GET_ORIG_SIZE(ptr) >= 0)) {
  209.         size = GET_ORIG_SIZE(ptr);
  210.     }
  211. #endif MEM_TRACE
  212.  
  213.     found = 0;
  214.     for (i = 0; i < MAX_TO_PRINT; i++) {
  215.         if (size == topN[i].size) {
  216.         found = 1;
  217.         topN[i].num++;
  218.         if (IS_DUMMY(admin)) {
  219.             topN[i].dummy++;
  220.         } else if (IS_IN_USE(admin)) {
  221.             topN[i].inUse++;
  222.         } else {
  223.             topN[i].free++;
  224.         }
  225.         break;
  226.         } else if (topN[i].size == -1) {
  227.         found = 1;
  228.         topN[i].size = size;
  229.         topN[i].num = 1;
  230.         if (IS_DUMMY(admin)) {
  231.             topN[i].dummy = 1;
  232.         } else if (IS_IN_USE(admin)) {
  233.             topN[i].inUse = 1;
  234.         } else {
  235.             topN[i].free = 1;
  236.         }
  237.         break;
  238.         }
  239.     }
  240.  
  241.     if (!found && !warnedAboutOverflow) {
  242.         (*memPrintProc)(memPrintData,
  243.             "Ran out of large-object bins: needed more than %d.\n",
  244.             size);
  245.         warnedAboutOverflow = 1;
  246.     }
  247.     }
  248.     (*memPrintProc)(memPrintData, "Large object allocator:\n");
  249.     (*memPrintProc)(memPrintData, "   Total bytes managed: %d\n",
  250.         mem_NumLargeBytes);
  251.     (*memPrintProc)(memPrintData, "   Bytes in use:        %d\n",
  252.                     mem_NumLargeBytes - freeBytes);
  253.     (*memPrintProc)(memPrintData, "%10s%10s%10s%10s\n", 
  254. #ifdef MEM_TRACE
  255.         "Orig. Size", "Num", "Free", "In Use");
  256. #else
  257.         "Size", "Num", "Free", "In Use");
  258. #endif MEM_TRACE
  259.     for (i = 0; topN[i].size != -1; i++) {
  260.     if (((topN[i].num >= mem_LargeMinNum)
  261.         || (topN[i].size >= mem_LargeMaxSize))
  262.         && (topN[i].num != topN[i].dummy)) {
  263.         (*memPrintProc)(memPrintData, "%10d%10d%10d%10d\n",
  264.         topN[i].size, topN[i].num, topN[i].free, topN[i].inUse);
  265.     }
  266.     }
  267. }
  268.